package mas;

import java.util.concurrent.LinkedBlockingQueue;

/** Class models a generic agent which extends blocking queue and can be 
 * extended to add additional functionality
 * 
 * Represents one MetaAgent.
 * Advanced Java Programming - ICA 2 Middleware 
 * @author Carl Morphet, Matt Constable, Stephen Pammenter
 * Teesside University
 * Created: Mar 20, 2012
 * @version %I%
 */
public class MetaAgent extends BlockingQueue implements Runnable
{
    /** The portal linked to this instance of MetaAgent */
    private Portal portal;
    
    /** The identifier for this MetaAgent instance */
    private String name;
    
    /** The terminating string, which when passed will stop further queuing */
    private static final String SHUTDOWN_REQ = "SHUTDOWN";
    
    /** The MetaAgents message queue */
    protected LinkedBlockingQueue itemsToQueue = new LinkedBlockingQueue();

    /** Constructor which takes a String parameter which acts as the MetaAgents 
     * identifier
     * 
     * @param name The MetaAgents identifier
     */
    public MetaAgent(String name)
    {
         this.name = name;
         new Thread(this).start();
    }
    
    /** Mutator method which sets this instance of MetaAgents portal to the
     * portal passed as a parameter
     * 
     * @param p The portal relating to this MetaAgent
     */
    protected void setPortal(Portal p)
    {
        this.portal = p;
    }
    
    /** Accessor method which returns this MetaAgents portal instance
     * 
     * @return The portal relating to this MetaAgent instance
     */
    protected Portal getPortal()
    {
        return portal;
    }
    
    /** This method is called when the MetaAgents thread is started in the 
     * constructor, it checks if there is a message on the queue, if there is 
     * it checks if it contains the shutdown command, if not it passes the 
     * message to the msgHandler() method. 
     */
    @Override
    public void run()
    {
        try
        {
            Message item = (Message)itemsToQueue.take();
            
            while((! item.getID().equals(SHUTDOWN_REQ)))
            {
                msgHandler((Message) itemsToQueue.take());
            }
        }
        catch(InterruptedException iex)
        {
            System.err.println("Meta Agent error: " + iex.getMessage());
        }
    }
    
    /** Method which handles messages received by the MetaAgent appropriately, 
     * in this case printing the message to the GUI
     * 
     * @param m The message to be handled
     */
    public void msgHandler(Message m)
    {
        if(m.getID().equals(SHUTDOWN_REQ))
        {
            if(itemsToQueue.isEmpty())
            {
                System.exit(0);             //Standard System exit
            }
            else
            {
                System.out.println("Cannot exit yet, items still to be handled");
            }
        }
        
        String id = m.getID();
        String sender = m.getSender();
        String recipient = m.getRecipient();
        String messageContent = m.getMessage();
        
        //Print to GUI
        System.out.println("Message ID: " + id + "\nMessage from: " + sender + 
                           "\nMessage to: " + recipient + "\nMessage Content: " 
                           + messageContent + "\n");
    }
    
    /** Overridden toString() method which returns the agents name, used
     * primarily in debugging
     * 
     * @return The agents identifier
     */
    @Override
    public String toString()
    {
        return name;
    }
}